#include "Camera.h"
#include <iostream>
using namespace std;

Camera::Camera()
{
	position[0] = 0.0f;
	position[1] = 0.0f;
	position[2] = 0.0f;
	R = 0.0f;
}

Camera::~Camera()
{
}

void Camera::Pan(float x, float y)
{
	/**
	Move the camera.
	*/

	position[0] = x;
	position[1] = y;
}

void Camera::Rotate(float r)
{
	/**
	Set The Camera's Rotation (default 0.0f)
	*/
	R = r;
}

void Camera::Zoom(float z)
{
	/**
	Set Z Camera Position. In this case it's used as the camera's zoom factor. (default 0.0f)
	*/
	position[2] = z;
}

void Camera::Center(Entity * object)
{
	/**
	Center The camera on a object
	*/

	if(object != NULL)
	{
		position[0] = -object->GetXPosition();
		position[1] = -object->GetYPosition();

		D3DXMatrixTranslation(&cameraMatrix, position[0], position[1], position[2]);

		//_cprintf("%f %f\n", position[0], position[1]);
	}
	else
		_cprintf("No object to center on!\n");
}

float Camera::GetXPosition()
{
	/**
	Return X Position of Camera
	*/
	return position[0];
}

float Camera::GetYPosition()
{
	/**
	Return Y Position of Camera
	*/
	return position[1];
}

float Camera::GetZPosition()
{
	/**
	Return Z Position of Camera
	*/
	return position[2];
}

float Camera::GetRotation()
{
	/**
	Return Camera Rotation
	*/
	return R;
}

D3DXMATRIXA16 * Camera::GetMatrix()
{
	/**
	Return Camera Matrix
	*/
	return &cameraMatrix;
}

void Camera::buildFrustum(LPDIRECT3DDEVICE9 d3ddev)
{
	/**
	Construct the planes for the frustum.
	*/

	D3DXMATRIXA16 projection;
	D3DXMATRIXA16 view;
	D3DXMATRIXA16 viewProjection;

	d3ddev->GetTransform( D3DTS_PROJECTION, &projection);
	d3ddev->GetTransform( D3DTS_VIEW, &view);

	//viewProjection = cameraMatrix * projection;
	viewProjection = cameraMatrix * view * projection;
	//viewProjection = projection * view * cameraMatrix;

	// Left plane
	frustum[0].a = viewProjection._14 + viewProjection._11;
	frustum[0].b = viewProjection._24 + viewProjection._21;
	frustum[0].c = viewProjection._34 + viewProjection._31;
	frustum[0].d = viewProjection._44 + viewProjection._41;

	// Right plane
	
	frustum[1].a = viewProjection._14 - viewProjection._11;
	frustum[1].b = viewProjection._24 - viewProjection._21;
	frustum[1].c = viewProjection._34 - viewProjection._31;
	frustum[1].d = viewProjection._44 - viewProjection._41;


	// Top plane
	
	frustum[2].a = viewProjection._14 - viewProjection._12;
	frustum[2].b = viewProjection._24 - viewProjection._22;
	frustum[2].c = viewProjection._34 - viewProjection._32;
	frustum[2].d = viewProjection._44 - viewProjection._42;

	// Bottom plane
	frustum[3].a = viewProjection._14 + viewProjection._12;
	frustum[3].b = viewProjection._24 + viewProjection._22;
	frustum[3].c = viewProjection._34 + viewProjection._32;
	frustum[3].d = viewProjection._44 + viewProjection._42;

	// Near plane
	frustum[4].a = viewProjection._13;
	frustum[4].b = viewProjection._23;
	frustum[4].c = viewProjection._33;
	frustum[4].d = viewProjection._43;

	// Far plane
	frustum[5].a = viewProjection._14 - viewProjection._13;
	frustum[5].b = viewProjection._24 - viewProjection._23;
	frustum[5].c = viewProjection._34 - viewProjection._33;
	frustum[5].d = viewProjection._44 - viewProjection._43; 
	
	//Normalize Planes
	for(int i=0; i<6; i++)
		D3DXPlaneNormalize(&frustum[i], &frustum[i]);
	
}

bool Camera::sphereInFrustum(Entity * object, float radius)
{
	/**
	Check to see if the object is completely inside the frustum. (Uses a bounding sphere)
	*/

	for(int i=0; i<6; i++)
		if( D3DXPlaneDotCoord( &frustum[i], &D3DXVECTOR3(object->GetXPosition(), object->GetYPosition(), object->GetZPosition())) + radius < 0 )
			return false;

	return true;
}

bool Camera::boxInFrustum(Entity * object)
{
	/**
	Check to see if the object is completely inside the frustum. (Uses a bounding box)
	*/

	return 1;
}